﻿using DotNetExtensions.Core.IOC;
using DotNetExtensions.Core.Logging;
using DotNetExtensions.Core.Restful;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace DotNetExtensions.Core.WebApi.Middlewares
{
    [AutoInject]
    public class GlobalExceptionHandler : IMiddleware
    {
        public GlobalExceptionHandler()
        {

        }
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            try
            {
                context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                context.Response.Headers.Add("Access-Control-Allow-Methods", "*");
                context.Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type");
                await next(context);
            }
            catch (Exception ex)
            {
                await HandleExceptionAsync(context, ex, 500);
            }
            finally
            {
                switch (context.Response.StatusCode)
                {
                    case 401:
                        await HandleExceptionAsync(context, new Exception("未授权，登录已失效或异地登录。"), context.Response.StatusCode);
                        break;
                    case 404:
                    case 405:
                        await HandleExceptionAsync(context, new Exception("未找到服务[" + context.Request.Method + ":" + context.Request.Path + "]，或者请求方式不正确。"), context.Response.StatusCode);
                        break;
                    case 500:
                        await HandleExceptionAsync(context, new Exception("请求发生错误，请查看日志。"), context.Response.StatusCode);
                        break;
                }
            }
        }

        private static Task HandleExceptionAsync(HttpContext context, Exception exception, int code)
        {
            if (exception is HandledException handled)
            {
                return handled.WriteAsync(context.Response);
            }
            else
            {
                ApiResult result = ApiResult.Failed(exception.Message);
                result.Code = code;
                context.Response.ContentType = "application/json";
                context.Response.StatusCode = (int)HttpStatusCode.OK;

                ILogger logger = LoggerManager.GetLogger("GlobalException");
                logger.LogError($"[" + code + "] [Http Request Url] {context.Request.Path} [Message]{exception.Message} [StackTrace] {exception.StackTrace}");
                string data = JsonConvert.SerializeObject(result, new JsonSerializerSettings
                {
                    ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
                });
                return context.Response.WriteAsync(data);
            }
        }
    }
}
